home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 1997 #1
/
Amiga Plus CD - 1997 - No. 01.iso
/
pd
/
programmierung
/
oberonv4
/
demos
/
mines.mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1996-05-27
|
38KB
|
1,199 lines
Syntax10.Scn.Fnt
Syntax10b.Scn.Fnt
FoldElems
Syntax10.Scn.Fnt
(* standard colors *)
Syntax10.Scn.Fnt
(*MS-Windows Colors*)
MODULE Mines; (** Oberon-Mines V1.32 (C) 1 Oct 95 by Ralf Degner *)
(* If you use MacOberon or the Ceres replace Input.TimeUnit by 300 *)
IMPORT
Oberon, Texts, Display, MenuViewers, TextFrames, Input, Fonts, Viewers, Files;
CONST
(* the colors of Mines with Mines.Pal *)
black=Display.white; red=1; yellow=4; lightgray=12; midgray=13; darkgray=14;
Col1=3; Col2=2; Col3=red; Col4=9; Col5=7; Col6=5; Col7=6; Col8=black;
(* the colors of Mines for Windows *)
(*black=Display.white; red=1; yellow=10; lightgray=11; midgray=12; darkgray=14;
Col1=3; Col2=5; Col3=red; Col4=6; Col5=4; Col6=8; Col7=7; Col8=black;*)
Menu = "System.Close System.Copy System.Grow Mines.Pause Mines.Beginner Mines.Advanced Mines.Expert Mines.Max Mines.Score";
KastenBreite=16;ObenPlatz=25;
UntenPlatz=4;SeitenPlatz=4;
KastenPlatz*=KastenBreite+1;KB=KastenBreite;
MinKastenAnz=7;CharBreite=8;
FeldPtr* = POINTER TO ARRAY OF ARRAY OF SHORTINT;
String = ARRAY 32 OF CHAR;
Data* = POINTER TO DataDesc;
DataDesc* = RECORD
XKastenAnz*,YKastenAnz*: INTEGER;
Aktiv*, Pause*, StartPlay*: BOOLEAN;
Feld*: FeldPtr;
Time*, Count*, Mines*: LONGINT;
Quote*, Mode*: INTEGER;
END;
Frame* = POINTER TO FrameDesc;
FrameDesc* = RECORD(Display.FrameDesc)
SeitenOffset*, UntenOffset*: INTEGER;
LastModMsg: BOOLEAN;
d*: Data;
END;
MinerMsg = RECORD(Display.FrameMsg)
d*: Data;
END;
PlotNewMsg = RECORD(MinerMsg)
END;
PlotKastenMsg* = RECORD(MinerMsg)
x*, y*: INTEGER;
END;
NeuesFeldMsg = RECORD(MinerMsg)
Change: BOOLEAN;
END;
RePlotMsg = RECORD(MinerMsg)
All: BOOLEAN;
END;
TimeMsg = RECORD(MinerMsg)
id: LONGINT;
Count: INTEGER;
END;
UsedFont: Fonts.Font;
W: Texts.Writer;
TimeTask: Oberon.Task;
seed, StartTime, LastTime: LONGINT;
HiTime: ARRAY 3 OF LONGINT;
HiName: ARRAY 3 OF String;
Name: String;
ScoreFile: Files.File;
ScoreRider: Files.Rider;
Color, UseTimeTask, TimeTaskRuns, PauseFlag: BOOLEAN;
Colors: ARRAY 8 OF INTEGER;
Dummy: INTEGER;
TimeUnit: LONGINT;
(* data for patterns *)
HappyData, SadData, BackData, GotItData, PauseData: ARRAY 17 OF SET;
HappyPat, SadPat, BackPat, GotItPat, PausePat: LONGINT;
Data1, Data2, Data3, Data4: ARRAY 13 OF SET;
Pat: ARRAY 5 OF LONGINT;
(* clear HiScore *)
PROCEDURE ClearHi;
VAR d: INTEGER;
BEGIN
FOR d:=0 TO 2 DO
HiTime[d]:=999999;
HiName[d]:="Amiga"
END ClearHi;
(* store HiScore *)
PROCEDURE SaveHi(Register: BOOLEAN);
VAR d: INTEGER;
BEGIN
Files.Set(ScoreRider, ScoreFile, 0);
Files.WriteBool(ScoreRider, Color);
Files.WriteBool(ScoreRider, UseTimeTask);
FOR d:=0 TO 2 DO
Files.WriteLInt(ScoreRider, HiTime[d]);
Files.WriteBytes(ScoreRider, HiName[d], 32);
END;
IF Register THEN
Files.Register(ScoreFile)
ELSE
Files.Close(ScoreFile)
END
END SaveHi;
(* load HiScore *)
PROCEDURE LoadHi;
VAR d: INTEGER;
BEGIN
ClearHi();
ScoreFile:=Files.Old("Mines.Score");
IF ScoreFile=NIL THEN
ScoreFile:=Files.New("Mines.Score");
SaveHi(TRUE)
ELSE
Files.Set(ScoreRider, ScoreFile, 0);
Files.ReadBool(ScoreRider, Color);
Files.ReadBool(ScoreRider, UseTimeTask);
FOR d:=0 TO 2 DO
Files.ReadLInt(ScoreRider, HiTime[d]);
Files.ReadBytes(ScoreRider, HiName[d], 32)
END
END LoadHi;
(* produces random numbers *)
PROCEDURE Random(Ein: INTEGER):INTEGER;
CONST a=16807; m=2147483647; q=m DIV a; r=m MOD a;
VAR g: LONGINT;
BEGIN
g:=a*(seed MOD q)-r*(seed DIV q);
IF g>0 THEN seed:=g
ELSE seed:=g+m END;
RETURN SHORT(seed) MOD Ein
END Random;
(* stop the TimeTask *)
PROCEDURE StopTask*;
BEGIN
IF TimeTaskRuns THEN
Oberon.Remove(TimeTask);
TimeTaskRuns:=FALSE
END StopTask;
(* the task that sends a TimeMsg every second *)
PROCEDURE TheTimeTask;
VAR timsg: TimeMsg;
BEGIN
IF Input.Time()>LastTime THEN
LastTime:=LastTime+TimeUnit;
timsg.id:=StartTime;
timsg.Count:=0;
Viewers.Broadcast(timsg);
IF timsg.Count=0 THEN StopTask() END
END TheTimeTask;
(* start the TimeTask *)
PROCEDURE StartTask;
BEGIN
IF ~TimeTaskRuns THEN
NEW(TimeTask);
TimeTask.safe:=FALSE;
TimeTask.handle:=TheTimeTask;
Oberon.Install(TimeTask);
LastTime:=Input.Time();
TimeTaskRuns:=TRUE
END StartTask;
(* draw box at top of the field *)
PROCEDURE PlotSmily(f: Frame; Smile: BOOLEAN);
VAR XPos, YPos, Col: INTEGER;
BEGIN
IF f.H>ObenPlatz THEN
IF f.W>30 THEN
YPos:=f.Y+f.H-ObenPlatz+3;
XPos:=f.W DIV 2-10+f.X;
IF Color THEN
Display.ReplConst(lightgray, XPos, YPos, 20, 20, Display.replace);
Display.ReplConst(darkgray, XPos+1, YPos, 19, 19, Display.replace);
Display.ReplConst(midgray, XPos+1, YPos+1, 18, 18, Display.replace);
Display.CopyPattern(yellow, BackPat, XPos+2, YPos+2, Display.paint);
Col:=black
ELSE
Display.ReplConst(Display.white, XPos, YPos, 20, 20, Display.replace);
Display.ReplConst(Display.black, XPos+1, YPos+1, 18, 18, Display.replace);
Col:=Display.white;
END;
IF f.d.Pause THEN
Display.CopyPattern(Col, PausePat, XPos+2, YPos+2, Display.paint)
ELSE
IF Smile THEN
Display.CopyPattern(Col, HappyPat, XPos+2, YPos+2, Display.paint)
ELSE
Display.CopyPattern(Col, SadPat, XPos+2, YPos+2, Display.paint)
END
END
END
END PlotSmily;
(* clear a frame *)
PROCEDURE ClearFrame(f: Frame; Smile: BOOLEAN);
BEGIN
Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
Display.ReplConst(Display.black, f.X, f.Y, f.W, f.H, Display.replace);
f.SeitenOffset:=(f.W-f.d.XKastenAnz*KastenPlatz) DIV 2 +f.X;
f.UntenOffset:=f.Y+f.H-ObenPlatz-f.d.YKastenAnz*KastenPlatz;
PlotSmily(f, Smile);
END ClearFrame;
(* copy frame with same data *)
PROCEDURE CopyMe(f: Frame): Frame;
VAR nf: Frame;
BEGIN
NEW(nf);IF nf=NIL THEN RETURN NIL;END;
nf.handle:=f.handle;
nf.d:=f.d;nf.LastModMsg:=TRUE;
RETURN nf;
END CopyMe;
(* clear a box *)
PROCEDURE ClearKasten(f: Frame; x, y: INTEGER; Color: BOOLEAN);
VAR dumx, dumy: INTEGER;
BEGIN
dumx:=f.SeitenOffset+x*KastenPlatz-KastenBreite;
dumy:=f.UntenOffset+y*KastenPlatz-KastenBreite;
IF Color THEN
Display.ReplConst(darkgray, dumx, dumy, KB, KB, Display.replace);
Display.ReplConst(lightgray, dumx+1, dumy, KB-1, KB-1, Display.replace);
Display.ReplConst(midgray, dumx+1, dumy+1, KB-2, KB-2, Display.replace)
ELSE
Display.ReplConst(Display.black, dumx, dumy, KB, KB, Display.replace)
END ClearKasten;
(* draw not selected box *)
PROCEDURE BlockKasten(f: Frame; x, y: INTEGER; Color: BOOLEAN; col: INTEGER);
VAR dumx, dumy: INTEGER;
BEGIN
dumx:=f.SeitenOffset+x*KastenPlatz-KastenBreite;
dumy:=f.UntenOffset+y*KastenPlatz-KastenBreite;
IF Color THEN
Display.ReplConst(lightgray, dumx, dumy, KB, KB, Display.replace);
Display.ReplConst(darkgray, dumx+1, dumy, KB-1, KB-1, Display.replace);
Display.ReplConst(midgray, dumx+1, dumy+1, KB-2, KB-2, Display.replace)
ELSE
Display.ReplConst(Display.black, dumx, dumy, KB, KB, Display.replace);
Display.ReplConst(col, dumx+1, dumy+1, KB-2, KB-2, Display.replace)
END BlockKasten;
(* draw char at box *)
PROCEDURE DrawChar(f: Frame; ch: CHAR; XKasten, YKasten: INTEGER; Color: BOOLEAN; col: INTEGER);
Pat: Display.Pattern;
dx, x, y, w, h: INTEGER;
dumx, dumy: INTEGER;
BEGIN
Display.GetChar(UsedFont.raster, ch, dx, x, y, w, h, Pat);
ClearKasten(f, XKasten, YKasten, Color);
dumx:=f.SeitenOffset+XKasten*KastenPlatz-KastenBreite+(KB-w) DIV 2;
dumy:=f.UntenOffset+YKasten*KastenPlatz-KastenBreite+(KB-h) DIV 2;
IF Color THEN
col:=Colors[ORD(ch)-49];
END;
Display.CopyPattern(col, Pat, dumx, dumy, Display.paint);
END DrawChar;
(* draw char at x y to display *)
PROCEDURE DrawZahl(ch: CHAR; XPos, YPos: INTEGER);
Pat: Display.Pattern;
dx, x, y, w, h: INTEGER;
BEGIN
Display.GetChar(UsedFont.raster, ch, dx, x, y, w, h, Pat);
IF Color THEN
h:=black
ELSE
h:=Display.white;
END;
Display.CopyPattern(h, Pat, XPos+x, YPos+y, Display.paint);
END DrawZahl;
(* draw LONGINT *)
PROCEDURE DrawInt(x, y: INTEGER; Zahl: LONGINT; DrawInt: BOOLEAN);
VAR Col, Anz: INTEGER;
BEGIN
Anz:=4;
IF Color THEN
Col:=midgray
ELSE
Col:=Display.black;
END;
Display.ReplConst(Col, x, y, Anz*CharBreite+10, KastenBreite-2, Display.replace);
IF DrawInt THEN
IF Zahl<0 THEN
DrawZahl("-", x+2, y+1);
Zahl:=ABS(Zahl);
END;
REPEAT
DrawZahl(CHR(Zahl MOD 10+48), x+Anz*CharBreite+1, y+2);
Zahl:=Zahl DIV 10;
DEC(Anz)
UNTIL (Zahl=0) OR (Anz=-1)
END DrawInt;
(* draw number of Mines to find *)
PROCEDURE DrawMinesToFind(f: Frame);
BEGIN
DrawInt((f.W-119) DIV 2+f.X+2, f.Y+f.H-ObenPlatz+6, f.d.Mines, TRUE);
END DrawMinesToFind;
(* draw the time *)
PROCEDURE DrawTime(f: Frame);
BEGIN
DrawInt(f.W DIV 2+f.X+16, f.Y+f.H-ObenPlatz+6, (Input.Time()-f.d.Time) DIV TimeUnit, f.d.StartPlay);
END DrawTime;
(* draw pattern, like mine *)
PROCEDURE DrawPat(f: Frame; XKasten, YKasten, No: INTEGER; Mode: BOOLEAN; Color: BOOLEAN; col: INTEGER);
VAR dumx, dumy: INTEGER;
BEGIN
IF Mode THEN
ClearKasten(f, XKasten, YKasten, Color)
ELSE
BlockKasten(f, XKasten, YKasten, Color, col);
END;
dumx:=f.SeitenOffset+XKasten*KastenPlatz-KastenBreite;
dumy:=f.UntenOffset+YKasten*KastenPlatz-KastenBreite;
IF Color THEN
IF No<3 THEN
Display.CopyPattern(black, Pat[1], dumx+2, dumy+2, Display.paint);
IF No=2 THEN
Display.CopyPattern(red, Pat[2], dumx+2, dumy+2, Display.paint)
END
ELSE
Display.CopyPattern(red, Pat[3], dumx+2, dumy+2, Display.paint);
Display.ReplConst(black, dumx+5, dumy+3, 1, 10, Display.replace)
END
ELSE
IF No=1 THEN
IF Mode THEN
Display.CopyPattern(col, Pat[1], dumx+2, dumy+2, Display.paint)
ELSE
Display.CopyPattern(Display.black, Pat[1], dumx+2, dumy+2, Display.paint)
END
ELSE
IF No=2 THEN No:=4;END;
Display.CopyPattern(Display.black, Pat[No], dumx+2, dumy+2, Display.paint)
END
END DrawPat;
(* invert char *)
PROCEDURE DrawCharInv(f: Frame; ch: CHAR; XKasten, YKasten: INTEGER);
Pat: Display.Pattern;
dx, x, y, w, h: INTEGER;
dumx, dumy: INTEGER;
BEGIN
Display.GetChar(UsedFont.raster, ch, dx, x, y, w, h, Pat);
dumx:=f.SeitenOffset+XKasten*KastenPlatz-KB+(KB-w) DIV 2;
dumy:=f.UntenOffset+YKasten*KastenPlatz-KB+(KB-h) DIV 2;
Display.CopyPattern(Display.white, Pat, dumx, dumy, Display.invert);
END DrawCharInv;
(* make new data *)
PROCEDURE NeuesFeld*(d: Data; x, y: INTEGER);
ZaehlerX, ZaehlerY: INTEGER;
dummy: LONGINT;
Bomben: SHORTINT;
BEGIN
NEW(d.Feld, x+2, y+2);
IF d.Feld=NIL THEN
d.Aktiv:=FALSE;
RETURN;
END;
FOR ZaehlerX:=0 TO x+1 DO
FOR ZaehlerY:=0 TO y+1 DO
d.Feld[ZaehlerX, ZaehlerY]:=1
END
END;
dummy:=(LONG(x)*y*d.Quote) DIV 100;
d.Count:=LONG(x)*y-dummy;d.Mines:=dummy;
REPEAT
REPEAT
ZaehlerX:=Random(x)+1;
ZaehlerY:=Random(y)+1
UNTIL d.Feld[ZaehlerX, ZaehlerY]=1;
d.Feld[ZaehlerX, ZaehlerY]:=10;
DEC(dummy)
UNTIL dummy=0;
FOR ZaehlerX:=1 TO x DO
FOR ZaehlerY:=1 TO y DO
IF d.Feld[ZaehlerX, ZaehlerY]=1 THEN
Bomben:=1;
IF d.Feld[ZaehlerX+1, ZaehlerY]=10 THEN INC(Bomben);END;
IF d.Feld[ZaehlerX+1, ZaehlerY+1]=10 THEN INC(Bomben);END;
IF d.Feld[ZaehlerX, ZaehlerY+1]=10 THEN INC(Bomben);END;
IF d.Feld[ZaehlerX-1, ZaehlerY+1]=10 THEN INC(Bomben);END;
IF d.Feld[ZaehlerX-1, ZaehlerY]=10 THEN INC(Bomben);END;
IF d.Feld[ZaehlerX-1, ZaehlerY-1]=10 THEN INC(Bomben);END;
IF d.Feld[ZaehlerX, ZaehlerY-1]=10 THEN INC(Bomben);END;
IF d.Feld[ZaehlerX+1, ZaehlerY-1]=10 THEN INC(Bomben);END;
d.Feld[ZaehlerX, ZaehlerY]:=Bomben
END
END
END NeuesFeld;
(* draw a box *)
PROCEDURE DrawKasten*(f: Frame; XZaehler, YZaehler: INTEGER; Color: BOOLEAN; col: INTEGER);
VAR dummy: SHORTINT;
BEGIN
dummy:=f.d.Feld[XZaehler, YZaehler];
IF dummy>0 THEN
IF dummy>16 THEN
DrawPat(f, XZaehler, YZaehler, 3, FALSE, Color, col)
ELSE
BlockKasten(f, XZaehler, YZaehler, Color, col)
END
ELSE
IF dummy=-10 THEN
DrawPat(f, XZaehler, YZaehler, 1, TRUE, Color, col)
ELSIF dummy=-1 THEN
ClearKasten(f, XZaehler, YZaehler, Color)
ELSE
DrawChar(f, CHR(47-dummy), XZaehler, YZaehler, Color, col)
END
END DrawKasten;
(* draw all *)
PROCEDURE PlotAll(f: Frame);
VAR xdum, ydum: INTEGER;
BEGIN
xdum:=(f.W-7*KastenPlatz) DIV 2+f.X+2;
ydum:=f.Y+f.H-ObenPlatz+6;
IF Color THEN
Display.ReplConst(lightgray, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace);
Display.ReplConst(darkgray, xdum, ydum-1, 4*CharBreite+11, KastenBreite-1, Display.replace);
xdum:=f.W DIV 2+f.X+16;
Display.ReplConst(lightgray, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace);
Display.ReplConst(darkgray, xdum, ydum-1, 4*CharBreite+11, KastenBreite-1, Display.replace)
ELSE
Display.ReplConst(Display.white, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace);
xdum:=f.W DIV 2+f.X+16;
Display.ReplConst(Display.white, xdum-1, ydum-1, 4*CharBreite+12, KastenBreite, Display.replace);
END;
DrawMinesToFind(f);
DrawTime(f);
ydum:=f.d.YKastenAnz*KastenPlatz+1;
xdum:=f.d.XKastenAnz*KastenPlatz+1;
IF Color THEN
Display.ReplConst(midgray, f.SeitenOffset, f.UntenOffset, xdum, ydum, Display.replace);
Display.ReplConst(lightgray, f.SeitenOffset-1, f.UntenOffset-1, 1, ydum+2, Display.replace);
Display.ReplConst(lightgray, f.SeitenOffset-1, f.UntenOffset+ydum, xdum+1, 1, Display.replace);
Display.ReplConst(darkgray, f.SeitenOffset-1, f.UntenOffset-1, xdum+2, 1, Display.replace);
Display.ReplConst(darkgray, f.SeitenOffset+xdum, f.UntenOffset-1, 1, ydum+2, Display.replace)
ELSE
Display.ReplConst(Display.white, f.SeitenOffset, f.UntenOffset, xdum, ydum, Display.replace);
END;
FOR xdum:=1 TO f.d.XKastenAnz DO
FOR ydum:=1 TO f.d.YKastenAnz DO
DrawKasten(f, xdum, ydum, Color, Display.white)
END
END PlotAll;
(* draw all, if finding a mine *)
PROCEDURE SwitchAll(f: Frame; Color: BOOLEAN; col: INTEGER);
xdum, ydum: INTEGER;
Typ: SHORTINT;
BEGIN
Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
FOR xdum:=1 TO f.d.XKastenAnz DO
FOR ydum:=1 TO f.d.YKastenAnz DO
Typ:=f.d.Feld[xdum, ydum];
IF Typ>0 THEN
IF Typ=10 THEN
DrawPat(f, xdum, ydum, 1, FALSE, Color, col)
ELSIF Typ<10 THEN
f.d.Feld[xdum, ydum]:=-Typ;
DrawKasten(f, xdum, ydum, Color, col)
ELSIF (Typ>16) & (Typ#26) THEN
DrawPat(f, xdum, ydum, 2, FALSE, Color, col)
END
END
END
END SwitchAll;
(* test if Raster fits to frame *)
PROCEDURE TestRaster(f: Frame): BOOLEAN;
VAR XMax,YMax: INTEGER;
BEGIN
XMax:=(f.W-SeitenPlatz*2) DIV KastenPlatz;
YMax:=(f.H-ObenPlatz-UntenPlatz) DIV KastenPlatz;
IF XMax<f.d.XKastenAnz THEN RETURN FALSE;END;
IF YMax<f.d.YKastenAnz THEN RETURN FALSE;END;
RETURN TRUE;
END TestRaster;
(* check if Raster fits to frame *)
PROCEDURE CheckRaster(f: Frame): BOOLEAN;
XMax,YMax: INTEGER;
Change, Aktiv: BOOLEAN;
XAnzNeu, YAnzNeu: INTEGER;
BEGIN
Change:=FALSE;Aktiv:=TRUE;
XMax:=(f.W-SeitenPlatz*2) DIV KastenPlatz;
YMax:=(f.H-ObenPlatz-UntenPlatz) DIV KastenPlatz;
IF XMax<MinKastenAnz THEN Aktiv:=FALSE;Change:=TRUE;END;
IF YMax<MinKastenAnz THEN Aktiv:=FALSE;Change:=TRUE;END;
IF XMax<f.d.XKastenAnz THEN
XAnzNeu:=XMax;Change:=TRUE
ELSE
XAnzNeu:=f.d.XKastenAnz;
END;
IF YMax<f.d.YKastenAnz THEN
YAnzNeu:=YMax;Change:=TRUE
ELSE
YAnzNeu:=f.d.YKastenAnz;
END;
IF Change THEN
IF Aktiv THEN
f.d.XKastenAnz:=XAnzNeu;f.d.YKastenAnz:=YAnzNeu;
f.d.Aktiv:=TRUE
ELSE
f.d.Aktiv:=FALSE;
END;
f.d.Mode:=-1;
END;
RETURN Change;
END CheckRaster;
(* check if field fits to frame; if not, creat new field *)
PROCEDURE CalcRaster (f: Frame): BOOLEAN;
VAR pnmsg: PlotNewMsg;
BEGIN
IF CheckRaster(f) THEN
pnmsg.d:=f.d;
IF f.d.Aktiv THEN
NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz);
END;
f.d.StartPlay:=FALSE;
Viewers.Broadcast(pnmsg);
RETURN TRUE
ELSE
RETURN FALSE
END CalcRaster;
(* search boxes with no mine on it *)
PROCEDURE SearchMore(d: Data; x, y: INTEGER);
Dummy: SHORTINT;
pkmsg: PlotKastenMsg;
BEGIN
IF (x=0) OR (y=0) OR (x>d.XKastenAnz) OR (y>d.YKastenAnz) THEN RETURN;END;
Dummy:=d.Feld[x, y];
IF (Dummy<0) OR (Dummy>9) THEN RETURN;END;
DEC (d.Count);
d.Feld[x, y]:=-Dummy;
pkmsg.d:=d;
pkmsg.x:=x;pkmsg.y:=y;
Viewers.Broadcast(pkmsg);
IF Dummy=1 THEN
SearchMore(d, x+1, y);SearchMore(d, x+1, y+1);
SearchMore(d, x,y+1);SearchMore(d, x-1, y+1);
SearchMore(d, x-1, y);SearchMore(d, x-1, y-1);
SearchMore(d, x, y-1);SearchMore(d, x+1, y-1)
END SearchMore;
(* new HIScore ? *)
PROCEDURE CheckHiScore(d: Data);
BEGIN
IF d.Mode>-1 THEN
IF d.Time<HiTime[d.Mode] THEN
Texts.WriteString(W, "New Hi-Score !!!");Texts.WriteLn(W);
Texts.Append(Oberon.Log, W.buf);
HiTime[d.Mode]:=d.Time;
HiName[d.Mode]:=Name;
SaveHi(FALSE)
END
END CheckHiScore;
(* all Mines found *)
PROCEDURE GotIt(f: Frame);
VAR XPos, YPos: INTEGER;
BEGIN
YPos:=f.Y+f.H-ObenPlatz+4;
XPos:=(f.W DIV 2)-9+f.X;
Display.CopyPattern(black, GotItPat, XPos+1, YPos+1, Display.paint);
f.d.Mines:=0;DrawMinesToFind(f);
END GotIt;
(* switch field *)
PROCEDURE SwitchKasten(f: Frame; XKasten, YKasten: INTEGER; Color: BOOLEAN; col: INTEGER);
timsg: TimeMsg;
pkmsg: PlotKastenMsg;
Dummy: SHORTINT;
BEGIN
IF ~f.d.Aktiv THEN RETURN; END;
Dummy:=f.d.Feld[XKasten, YKasten];
IF (Dummy>0) & (Dummy<16) THEN
pkmsg.d:=f.d;
pkmsg.x:=XKasten;pkmsg.y:=YKasten;
IF Dummy=10 THEN
f.d.Feld[XKasten, YKasten]:=-10;
f.d.Aktiv:=FALSE;
SwitchAll(f, Color, col);
Viewers.Broadcast(pkmsg)
ELSE
IF Dummy=1 THEN
SearchMore(f.d, XKasten, YKasten)
ELSE
f.d.Feld[XKasten, YKasten]:=-Dummy;
DEC(f.d.Count);
Viewers.Broadcast(pkmsg);
END;
IF f.d.Count=0 THEN
timsg.id:=StartTime;
timsg.Count:=0;
Viewers.Broadcast(timsg);
f.d.Aktiv:=FALSE;
f.d.Time:=(Input.Time()-f.d.Time) DIV TimeUnit;
CheckHiScore(f.d)
END
END
END SwitchKasten;
(* react on mouse keys *)
PROCEDURE MouseKeys*(f: Frame; XKasten, YKasten: INTEGER; Key: SET; Color: BOOLEAN; col: INTEGER);
Dummy: SHORTINT;
pkmsg: PlotKastenMsg;
BEGIN
Dummy:=f.d.Feld[XKasten, YKasten];
pkmsg.d:=f.d;
pkmsg.x:=XKasten;pkmsg.y:=YKasten;
IF Key={2} THEN
IF ~f.d.StartPlay THEN
f.d.StartPlay:=TRUE;
f.d.Time:=Input.Time();
END;
SwitchKasten(f, XKasten, YKasten, Color, col)
ELSIF Key={0} THEN
IF Dummy>0 THEN
IF Dummy<16 THEN
f.d.Feld[XKasten, YKasten]:=Dummy+16;
f.d.Mines:=f.d.Mines-1
ELSE
f.d.Feld[XKasten, YKasten]:=Dummy-16;
f.d.Mines:=f.d.Mines+1;
END;
Viewers.Broadcast(pkmsg)
END
ELSIF Key={0,2} THEN
IF Dummy<0 THEN
IF ~f.d.StartPlay THEN
f.d.StartPlay:=TRUE;
f.d.Time:=Input.Time();
END;
SwitchKasten(f, XKasten+1, YKasten, Color, col);
SwitchKasten(f, XKasten+1, YKasten-1, Color, col);
SwitchKasten(f, XKasten, YKasten-1, Color, col);
SwitchKasten(f, XKasten-1, YKasten-1, Color, col);
SwitchKasten(f, XKasten-1, YKasten, Color, col);
SwitchKasten(f, XKasten-1, YKasten+1, Color, col);
SwitchKasten(f, XKasten, YKasten+1, Color, col);
SwitchKasten(f, XKasten+1, YKasten+1, Color, col)
END
END MouseKeys;
(* get selected frame *)
PROCEDURE GetFrame(VAR f: Display.Frame): BOOLEAN;
VAR v: Viewers.Viewer;
BEGIN
IF Oberon.Par.frame=Oberon.Par.vwr.dsc THEN
IF (Oberon.Par.frame # NIL) THEN
f:=Oberon.Par.frame.next;
RETURN TRUE
END
ELSE
v:=Oberon.MarkedViewer();
IF (v.dsc # NIL) & (v.dsc.next # NIL) THEN
f:=v.dsc.next;
RETURN TRUE
END
END;
RETURN FALSE
END GetFrame;
(* Open new Text-Frame *)
PROCEDURE OpenViewer(text: Texts.Text);
VAR x, y: INTEGER; v: Viewers.Viewer; cf: TextFrames.Frame;
BEGIN
Oberon.AllocateSystemViewer(Oberon.Par.vwr.X, x, y);
cf := TextFrames.NewText(text, 0);
v := MenuViewers.New(TextFrames.NewMenu("Mines Hall Of Fame", "System.Close System.Copy System.Grow"),
cf, TextFrames.menuH, x, y)
END OpenViewer;
(* do the pause *)
PROCEDURE DoPause(f: Frame);
nfmsg: NeuesFeldMsg;
rpmsg: RePlotMsg;
pnmsg: PlotNewMsg;
BEGIN
IF f.d.Pause THEN
IF TestRaster(f) OR PauseFlag THEN
f.d.Pause:=FALSE;
nfmsg.d:=f.d;nfmsg.Change:=FALSE;
Viewers.Broadcast(nfmsg);
IF nfmsg.Change THEN
IF f.d.Aktiv THEN
NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz);
END;
pnmsg.d:=f.d;
Viewers.Broadcast(pnmsg);
f.d.StartPlay:=FALSE
ELSE
rpmsg.All:=FALSE;
rpmsg.d:=f.d;
f.d.Time:=Input.Time()-f.d.Time;
Viewers.Broadcast(rpmsg)
END
ELSE
Texts.WriteString(W, "Frame too small for old game !");
Texts.WriteLn(W);
Texts.Append(Oberon.Log, W.buf);
PauseFlag:=TRUE
END
ELSE
f.d.Pause:=TRUE;
f.d.Time:=Input.Time()-f.d.Time;
rpmsg.d:=f.d;rpmsg.All:=FALSE;
Viewers.Broadcast(rpmsg)
END DoPause;
(* set Pause mode *)
PROCEDURE Pause*;
f, g: Display.Frame;
BEGIN
IF GetFrame(g) THEN
f:=g;
WITH f: Frame DO
IF f.d.Aktiv THEN DoPause(f)END
ELSE
END
END Pause;
(* do mouseaction *)
PROCEDURE DoMou(f: Frame; X, Y: INTEGER; Key, FirstKey: SET);
XKasten, YKasten: INTEGER;
XStore, YStore: INTEGER;
Dummy: SHORTINT;
pnmsg: PlotNewMsg;
nfmsg: NeuesFeldMsg;
timsg: TimeMsg;
BEGIN
IF ~f.d.Pause THEN
XStore:=X;YStore:=Y;
X:=X-f.SeitenOffset;Y:=Y-f.UntenOffset;
IF X<0 THEN RETURN;END;
IF Y<0 THEN RETURN;END;
XKasten:=X DIV KastenPlatz +1;
YKasten:=Y DIV KastenPlatz +1;
IF (XKasten<=f.d.XKastenAnz) & (YKasten<=f.d.YKastenAnz) THEN
IF ~f.d.Aktiv THEN RETURN;END;
IF ((X MOD KastenPlatz)=0) OR ((Y MOD KastenPlatz)=0) THEN RETURN; END;
Dummy:=f.d.Feld[XKasten, YKasten];
IF Key={1} THEN
IF Dummy>0 THEN
IF Dummy<16 THEN
Oberon.RemoveMarks(f.SeitenOffset, f.UntenOffset, f.W, f.H);
DrawCharInv(f, "?", XKasten, YKasten)
END
END
ELSE
MouseKeys(f, XKasten, YKasten, Key, Color, Display.white);
END;
IF f.d.Count=0 THEN
GotIt(f)
ELSE
IF ~UseTimeTask THEN
timsg.id:=StartTime;
timsg.Count:=0;
Viewers.Broadcast(timsg)
END
END
ELSE
IF (YStore>f.Y+f.H-ObenPlatz+3) & (YStore<f.Y+f.H-3) THEN
IF (ABS(XStore-f.X-(f.W DIV 2))<10) THEN
IF Key={2} THEN
nfmsg.d:=f.d;
f.d.Aktiv:=TRUE;
Viewers.Broadcast(nfmsg);
IF f.d.Aktiv THEN
NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz);
END;
pnmsg.d:=f.d;
f.d.StartPlay:=FALSE;
Viewers.Broadcast(pnmsg)
END
END
END
END
END DoMou;
(* set mousecursor and call DoMouse if button is pressed *)
PROCEDURE TrackMouse*(f: Frame; X, Y: INTEGER; k: SET; Mou: PROCEDURE(f: Frame; X, Y: INTEGER; K, F: SET));
XPos, YPos: INTEGER;
NewKeys, FirstKey: SET;
BEGIN
XPos:=X;YPos:=Y;
FirstKey:=k;
REPEAT
Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, X, Y);
Input.Mouse(NewKeys, X, Y);
k:=k+NewKeys
UNTIL NewKeys={};
IF k#{} THEN Mou(f, XPos, YPos, k, FirstKey) END
END TrackMouse;
(* the Handler of the Miner-Frames*)
PROCEDURE Handler(f: Display.Frame; VAR m: Display.FrameMsg);
self: Frame;
dumY, dumH: INTEGER;
BEGIN
self:=f(Frame);
WITH m: Oberon.InputMsg DO
IF m.id=Oberon.track THEN TrackMouse(self, m.X, m.Y, m.keys, DoMou)END
| m: Oberon.CopyMsg DO
m.F:=CopyMe(self)
| m: MenuViewers.ModifyMsg DO
PauseFlag:=FALSE;
IF m.H=0 THEN
self.LastModMsg:=TRUE;
RETURN;
END;
IF self.d.Pause OR ~self.d.Aktiv THEN (* game is paused or not Aktiv *)
f.Y:=m.Y;f.H:=m.H;
ClearFrame(self, self.d.Aktiv)
ELSIF self.d.Aktiv THEN (* if Aktiv *)
IF m.id=MenuViewers.extend THEN (* extended *)
IF self.LastModMsg THEN (* extended from 0, CalcRaster new *)
f.Y:=m.Y;f.H:=m.H;
ClearFrame(self, TRUE);
IF ~CalcRaster(self) THEN (* if old Raster, then redraw *)
PlotAll(self);
END;
IF UseTimeTask THEN StartTask()END
ELSE
IF m.dY=0 THEN (* extended at the bootom, clear new area *)
Oberon.RemoveMarks(self.X, m.Y, self.W, m.H-self.H);
Display.ReplConst(Display.black, self.X, m.Y, self.W, m.H-self.H, Display.replace)
ELSE (* extended at the top, copy and clear new area *)
Oberon.RemoveMarks(self.X, self.Y, self.W, self.H+m.dY);
Display.CopyBlock(self.X, self.Y, self.W, self.H, self.X, self.Y+m.dY, Display.replace);
Display.ReplConst(Display.black, self.X, m.Y, self.W, m.H-self.H, Display.replace);
self.UntenOffset:=self.UntenOffset+m.dY
END
END
ELSIF m.id=MenuViewers.reduce THEN (* reduced *)
dumY:=f.Y;dumH:=f.H;
f.Y:=m.Y;f.H:=m.H;
IF TestRaster(self) THEN
IF m.dY#0 THEN (* if top moved, copy *)
Oberon.RemoveMarks(self.X, m.Y, self.W, m.H-m.dY);
Display.CopyBlock(self.X, dumY+dumH-m.H, self.W, m.H, self.X, m.Y, Display.replace);
self.UntenOffset:=self.UntenOffset-m.dY
END
ELSE
DoPause(self)
END
END
END;
self.LastModMsg:=FALSE
| m: MinerMsg DO
WITH m: RePlotMsg DO
IF m.All OR (m.d=self.d) THEN
ClearFrame(self, self.d.Aktiv);
IF self.d.Aktiv & ~self.d.Pause THEN
PlotAll(self)
END
END
| m: TimeMsg DO
IF m.id=StartTime THEN
IF self.d.Aktiv & ~self.d.Pause & self.d.StartPlay THEN
Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
DrawTime(self);
END;
INC(m.Count)
END
ELSE
IF m.d=self.d THEN
WITH m: PlotNewMsg DO (* Message for new Raster *)
IF self.d.Aktiv THEN
IF ~CalcRaster(self) THEN (* Raster OK for this Frame ? *)
ClearFrame(self, TRUE);
PlotAll(self)
END
ELSE
ClearFrame(self, FALSE)
END
| m: PlotKastenMsg DO (* PLot one box *)
Oberon.RemoveMarks(f.X, f.Y, f.W, f.H);
DrawKasten(self, m.x, m.y, Color, Display.white);
IF self.d.Feld[m.x, m.y]>0 THEN
DrawMinesToFind(self);
END;
IF ~self.d.Aktiv THEN PlotSmily(self, FALSE)END
| m: NeuesFeldMsg DO (* Check if new W & H are fitting to frame *)
IF CheckRaster(self) THEN
m.Change:=TRUE
END
ELSE
END
END
END
ELSE
END Handler;
(* get parameters *)
PROCEDURE GetPar*(VAR Quote, X, Y, Mode: INTEGER);
S: Texts.Scanner;
text: Texts.Text;
Dummy, StoreQuote: INTEGER;
beg, end, time: LONGINT;
BEGIN
StoreQuote:=Quote;
Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
Texts.Scan(S);
IF S.class=Texts.Char THEN
IF S.c="^" THEN
Oberon.GetSelection(text, beg, end, time);
IF time=-1 THEN RETURN; END;
Texts.OpenScanner(S, text, beg);
Texts.Scan(S)
ELSE
RETURN
END
END;
IF S.class=Texts.Int THEN
IF (S.i>0) & (S.i<90) THEN;
Quote:=SHORT(S.i);
IF (Mode=-1) OR (X#256) THEN
Texts.Scan(S);
IF S.class=Texts.Int THEN;
Dummy:=SHORT(S.i);
Texts.Scan(S);
IF S.class=Texts.Int THEN
IF (Dummy<6) OR (Dummy>127) THEN
X:=8
ELSE
X:=Dummy;
END;
IF (S.i<6) OR (S.i>127) THEN
Y:=8
ELSE
Y:=SHORT(S.i)
END
END
END
ELSE
IF Quote#StoreQuote THEN Mode:=-1 END
END
END
END GetPar;
(* set frame and parameters *)
PROCEDURE ShortNewPar(X, Y, Quote, Mode: INTEGER);
f, g: Display.Frame;
nfmsg: NeuesFeldMsg;
pnmsg: PlotNewMsg;
BEGIN
IF GetFrame(g) THEN
f:=g;
WITH f: Frame DO
GetPar(Quote, X, Y, Mode);
f.d.Quote:=Quote;f.d.Mode:=Mode;
f.d.XKastenAnz:=X;f.d.YKastenAnz:=Y;
f.d.Aktiv:=TRUE;f.d.Pause:=FALSE;
nfmsg.d:=f.d;
Viewers.Broadcast(nfmsg);
IF f.d.Aktiv THEN
NeuesFeld(f.d, f.d.XKastenAnz, f.d.YKastenAnz);
END;
pnmsg.d:=f.d;
f.d.StartPlay:=FALSE;
Viewers.Broadcast(pnmsg)
ELSE
END
END ShortNewPar;
(* Open MenuFrame with Mines.Menu.Text *)
PROCEDURE MenuFrame(): TextFrames.Frame;
mf: TextFrames.Frame;
buf: Texts.Buffer;
t: Texts.Text;
r: Texts.Reader;
end: LONGINT;
ch: CHAR;
BEGIN
IF Files.Old("Mines.Menu.Text")=NIL THEN
mf:=TextFrames.NewMenu("Mines", Menu)
ELSE
mf:=TextFrames.NewMenu("Mines", "");
NEW(t);Texts.Open(t, "Mines.Menu.Text");
Texts.OpenReader(r, t, 0);
REPEAT
Texts.Read(r, ch)
UNTIL r.eot OR (ch=0DX);
IF r.eot THEN
end:=t.len
ELSE
end:=Texts.Pos(r)-1;
END;
NEW(buf); Texts.OpenBuf(buf);
Texts.Save(t, 0, end, buf);Texts.Append(mf.text, buf)
END;
RETURN mf;
END MenuFrame;
(* set new username *)
PROCEDURE SetUser*;
S: Texts.Scanner;
text: Texts.Text;
beg, end, time: LONGINT;
BEGIN
Texts.OpenScanner(S, Oberon.Par.text, Oberon.Par.pos);
Texts.Scan(S);
IF S.class=Texts.Char THEN
IF S.c="^" THEN
Oberon.GetSelection(text, beg, end, time);
IF time=-1 THEN RETURN; END;
Texts.OpenScanner(S, text, beg);
Texts.Scan(S)
ELSE
RETURN
END
END;
IF S.class=Texts.Name THEN
COPY(S.s, Name);
END;
Texts.WriteString(W, "Current Username : ");
Texts.WriteString(W, Name);
Texts.WriteLn(W);
Texts.Append(Oberon.Log, W.buf);
END SetUser;
(* show Hi-Score *)
PROCEDURE Score*;
i: INTEGER;
te: Texts.Text;
BEGIN
te:=TextFrames.Text("");
IF Files.Old("Mines.Score.Text")=NIL THEN
Texts.WriteString(W, " Oberon-Mines Hall Of Fame ! ");Texts.WriteLn(W);
Texts.WriteString(W, "________________________________________________________");Texts.WriteLn(W)
ELSE
Texts.Open(te, "Mines.Score.Text");
END;
FOR i:=0 TO 2 DO
IF i=0 THEN Texts.WriteString(W, "Beginner")
ELSIF i=1 THEN Texts.WriteString(W, "Advanced")
ELSE Texts.WriteString(W, "Expert");END;
Texts.Write(W, CHR(9));
Texts.WriteInt(W, HiTime[i], 1);
Texts.WriteString(W, " sec"); Texts.Write(W, CHR(9));
Texts.WriteString(W, HiName[i]);
Texts.WriteLn(W);
END;
Texts.WriteLn(W);
Texts.WriteString(W, "Current Username : ");
Texts.WriteString(W, Name);
Texts.WriteLn(W);
Texts.Append(te, W.buf);
OpenViewer(te);
END Score;
(* create new frame with new data *)
PROCEDURE Open*;
x, y: INTEGER;
f: Frame;
v: MenuViewers.Viewer;
BEGIN
NEW(f);IF f=NIL THEN RETURN;END;
NEW(f.d);IF f.d=NIL THEN RETURN;END;
f.handle:=Handler;f.d.Aktiv:=TRUE;f.d.Quote:=16;
f.LastModMsg:=TRUE;f.d.Pause:=FALSE;
f.d.XKastenAnz:=256;f.d.YKastenAnz:=256;
f.d.Mode:=-1;f.d.StartPlay:=FALSE;
Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y);
v:=MenuViewers.New(MenuFrame(), f, TextFrames.menuH, x, y);
END Open;
(* switch between color ans b/w mode *)
PROCEDURE ColorMode*;
VAR rpmsg: RePlotMsg;
BEGIN
Color:=~Color;
rpmsg.All:=TRUE;
Viewers.Broadcast(rpmsg);
SaveHi(FALSE);
END ColorMode;
(* switches between task und mouse action time mode *)
PROCEDURE TimeMode*;
BEGIN
UseTimeTask:=~UseTimeTask;
IF UseTimeTask THEN
IF ~TimeTaskRuns THEN StartTask() END
ELSE
IF TimeTaskRuns THEN StopTask() END
END;
SaveHi(FALSE);
END TimeMode;
(* start different types of the game *)
PROCEDURE Beginner*;
BEGIN
ShortNewPar(8, 8, 15, 0);
END Beginner;
PROCEDURE Advanced*;
BEGIN
ShortNewPar(16, 16, 16, 1);
END Advanced;
PROCEDURE Expert*;
BEGIN
ShortNewPar(30, 16, 21, 2);
END Expert;
PROCEDURE Max*;
BEGIN
ShortNewPar(256, 256, 16, -1);
END Max;
PROCEDURE Start*;
BEGIN
ShortNewPar(8, 8, 16, -1);
END Start;
BEGIN
TimeUnit:=Input.TimeUnit; (* replace Input.TimeUnit by 300 at MacOberon and Ceres *)
UsedFont:=Fonts.This("Syntax14.Scn.Fnt");
Texts.OpenWriter(W);
Texts.WriteString(W, "Oberon-Mines V1.32");
Texts.WriteLn(W);
Texts.WriteString(W, "(C) 1 Oct 95 by Ralf Degner");
Texts.WriteLn(W);
Texts.Append(Oberon.Log, W.buf);
StartTime:=Input.Time();
seed:=StartTime;
TimeTaskRuns:=FALSE;
Color:=FALSE;UseTimeTask:=TRUE;
IF Oberon.User="" THEN
Name:="AMIGA"
ELSE
COPY(Oberon.User, Name);
END;
Colors[0]:=Col1;Colors[1]:=Col2;Colors[2]:=Col3;Colors[3]:=Col4;
Colors[4]:=Col5;Colors[5]:=Col6;Colors[6]:=Col7;Colors[7]:=Col8;
LoadHi();
(* install patterns *)
HappyData[1]:={5,6,7,8,9,10};
HappyData[2]:={3,4,11,12};
HappyData[3]:={2,13};
HappyData[4]:={1,5,6,7,8,9,10,14};
HappyData[5]:={1,4,11,14};
HappyData[6]:={0,3,12,15};
HappyData[7]:={0,7,8,15};
HappyData[8]:={0,7,8,15};
HappyData[9]:={0,15};
HappyData[10]:={0,15};
HappyData[11]:={0,15,5,6,9,10};
HappyData[12]:={1,14,5,6,9,10};
HappyData[13]:={1,14};
HappyData[14]:={2,13};
HappyData[15]:={3,4,11,12};
HappyData[16]:={5,6,7,8,9,10};
HappyPat:=Display.NewPattern(HappyData, 16, 16);
SadData:=HappyData;
SadData[5]:={1,5,6,7,8,9,10,14};
SadData[4]:={1,4,11,14};
SadData[6]:={0,15};
SadPat:=Display.NewPattern(SadData, 16, 16);
BackData[1]:={};
BackData[2]:={5,6,7,8,9,10};
BackData[3]:={3,4,5,6,7,8,9,10,11,12};
BackData[4]:={2,3,4,5,6,7,8,9,10,11,12,13};
BackData[5]:={2,3,4,5,6,7,8,9,10,11,12,13};
BackData[6]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14};
BackData[7]:={1,2,3,4,5,6,9,10,11,12,13,14};
BackData[8]:={1,2,3,4,5,6,9,10,11,12,13,14};
BackData[9]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14};
BackData[10]:={1,2,3,4,5,6,7,8,9,10,11,12,13,14};
BackData[11]:={1,2,3,4,7,8,11,12,13,14};
BackData[12]:={1,2,3,4,7,8,11,12,13,14};
BackData[13]:={2,3,4,5,6,7,8,9,10,11,12,13};
BackData[14]:={3,4,5,6,7,8,9,10,11,12};
BackData[15]:={5,6,7,8,9,10};
BackData[16]:={};
BackPat:=Display.NewPattern(BackData, 16, 16);
GotItData:=HappyData;
GotItData[12]:={1,4,5,6,7,8,9,10,11,14};
GotItData[11]:={0,3,4,5,6,9,10,11,12,15};
GotItData[10]:={0,2,4,5,6,9,10,11,13,15};
GotItData[9]:={0,1,5,6,7,8,9,10,14,15};
GotItPat:=Display.NewPattern(GotItData, 16, 16);
PauseData:=SadData;
PauseData[5]:={1,14};
PauseData[4]:={1,4,5,6,7,8,9,10,11,14};
PausePat:=Display.NewPattern(PauseData, 16, 16);
(* Mine *)
Data1[1]:={3,4,5,6,7,8};
Data1[2]:={2,3,4,5,6,7,8,9};
Data1[3]:={1,2,3,5,6,7,8,9,10};
Data1[4]:={1,2,5,6,7,8,9,10};
Data1[5]:={1,2,4,5,6,7,8,9,10};
Data1[6]:={1,2,3,4,5,6,7,8,9,10};
Data1[7]:={2,3,4,5,6,7,8,9};
Data1[8]:={3,4,5,6,7,8};
Data1[9]:={5,6};
Data1[10]:={5};
Data1[11]:={6,10};
Data1[12]:={7,8,9};
Pat[1]:=Display.NewPattern(Data1, 12, 12);
(* No Mine *)
Data2[1]:={0,11};
Data2[2]:={1,10};
Data2[3]:={2,9};
Data2[4]:={3,8};
Data2[5]:={4,7};
Data2[6]:={5,6};
Data2[7]:={5,6};
Data2[8]:={4,7};
Data2[9]:={3,8};
Data2[10]:={2,9};
Data2[11]:={1,10};
Data2[12]:={0,11};
Pat[2]:=Display.NewPattern(Data2, 12, 12);
(* Flag *)
Data3[1]:={};
Data3[2]:={3};
Data3[3]:={3};
Data3[4]:={3};
Data3[5]:={3};
Data3[6]:={3};
Data3[7]:={3,4,5};
Data3[8]:={3,4,5,6,7};
Data3[9]:={3,4,5,6,7,8,9};
Data3[10]:={3,4,5,6,7};
Data3[11]:={3,4,5};
Data3[12]:={};
Pat[3]:=Display.NewPattern(Data3, 12, 12);
(* No Mine - No Color *)
FOR Dummy:=1 TO 12 DO
Data4[Dummy]:=Data1[Dummy]/Data2[Dummy];
END;
Pat[4]:=Display.NewPattern(Data4, 12, 12)
END Mines.Open
System.Free MinesElems Mines ~